const express = require('express');
const fs = require('fs');
const path = require('path');
const puppeteer = require('puppeteer');

const app = express();
app.use(express.json({ limit: '200mb' })); // 可选：限制大小

// 捕获 JSON 解析错误
app.use((err, req, res, next) => {
  if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
    console.error('❌ 请求体不是合法 JSON');
    return res.status(400).json({ error: 'Invalid JSON' });
  }
  next();
});

app.use('/templates', express.static(path.join(__dirname, 'templates')));


let browser = null;

// ========================
// 启动 Puppeteer 并自动重启
// ========================
async function launchBrowser() {
  console.log('🚀 正在启动 Puppeteer 浏览器...');
  const newBrowser = await puppeteer.launch({
    headless: 'new',
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-gpu',
      '--disable-dev-shm-usage'
    ]
  });

  newBrowser.on('disconnected', () => {
    console.warn('⚠️ 浏览器意外关闭，准备重启...');
    if (browser === newBrowser) {
      browser = null;
      setTimeout(() => {
        launchBrowser().catch(err => {
          console.error('🔁 自动重启失败:', err);
          setTimeout(launchBrowser, 5000); // 继续重试
        });
      }, 2000);
    }
  });

  return newBrowser;
}

// ========================
// 打印接口信息
// ========================
function printRoutes() {
  console.log('📌 接口列表：');
  console.log('────────────────────────────────────');
  console.log('📄 GET  /templates');
  console.log('   获取所有可用的 HTML 模板文件名');
  console.log('   示例: GET http://localhost:3000/templates\n');

  console.log('🖨️  POST /generate-pdf');
  console.log('   根据模板生成 PDF');
  console.log('   请求体: { "template": "paper", "data": { ... } }');
  console.log('   页面中会将 data 注入进 window.__PDF_DATA__ 对象');
  console.log('   响应: PDF 二进制流');
  console.log('   示例: POST http://localhost:3000/generate-pdf\n');


  console.log('🌐 POST /url-to-pdf');
  console.log('   将网页 URL 转为 PDF');
  console.log('   请求体: { "url": "http://example.com", "pdfOptions": { ... } }');
  console.log('   响应: PDF 二进制流');
  console.log('   示例: POST http://localhost:3000/url-to-pdf\n');


  console.log('✅ GET  /health');
  console.log('   健康检查，查看浏览器状态');
  console.log('   示例: GET http://localhost:3000/health\n');
}

// ========================
// 打印可用模板
// ========================
function printTemplates() {
  const templateDir = path.join(__dirname, 'templates');
  fs.readdir(templateDir, (err, files) => {
    if (err) {
      console.error('❌ 读取模板目录失败:', err);
      return;
    }
    const htmlFiles = files.filter(file => path.extname(file) === '.html');
    console.log('📂 当前可用模板:', htmlFiles.length > 0 ? htmlFiles : '无');
    console.log('────────────────────────────────────');
  });
}

// ========================
// 健康检查
// ========================
app.get('/health', (req, res) => {
  if (browser && browser.isConnected()) {
    res.json({ status: 'ok', browser: 'connected' });
  } else {
    res.status(503).json({ status: 'error', browser: 'disconnected' });
  }
});

// ========================
// 获取所有模板
// ========================
app.get('/templates', (req, res) => {
  const templateDir = path.join(__dirname, 'templates');
  fs.readdir(templateDir, (err, files) => {
    if (err) {
      return res.status(500).json({ error: '读取模板失败' });
    }
    const htmlFiles = files.filter(file => path.extname(file) === '.html');
    res.json({ templates: htmlFiles });
  });
});

// ========================
// 生成 PDF
// ========================
app.post('/generate-pdf', async (req, res) => {
  const { template, data = {} } = req.body;
  const start = Date.now();
  console.log(`\n🖨️ 开始生成 PDF | 模板: ${template} | 时间: ${new Date().toISOString()}`);

  // 检查 browser 状态
  if (!browser || !browser.isConnected()) {
    console.error('❌ 浏览器未连接，请求失败');
    return res.status(500).json({ error: '服务暂时不可用，请稍后重试' });
  }

  try {
    const templatePath = path.join(__dirname, 'templates', `${template}.html`);
    if (!fs.existsSync(templatePath)) {
      console.error(`❌ 模板不存在: ${template}.html`);
      return res.status(404).json({ error: '模板未找到' });
    }

    let html = fs.readFileSync(templatePath, 'utf8');

    // 注入数据
    const scriptTag = `<script>window.__PDF_DATA__ = ${JSON.stringify(data)};</script>`;
    html = html.replace('<body>', '<body>' + scriptTag);

    const page = await browser.newPage();
    page.on('console', msg => console.log('[PAGE] ' + msg.text()));
    page.on('error', err => console.error('[PAGE ERROR] ' + err));
    page.on('pageerror', err => console.error('[PAGE EXCEPTION] ' + err.message));

    await page.setContent(html, { waitUntil: 'networkidle0' });

    const pdfBuffer = await page.pdf({
      format: 'A4',
      printBackground: true,
      margin: {
        top: '20px',
        right: '20px',
        bottom: '20px',
        left: '20px'
      }
    });

    await page.close();

    const duration = Date.now() - start;
    console.log(`✅ PDF 生成成功 | 耗时: ${duration}ms`);

    res.set({
      'Content-Type': 'application/pdf',
      'Content-Length': pdfBuffer.length,
      'Content-Disposition': 'attachment; filename=document.pdf'
    });
    res.send(pdfBuffer);

  } catch (error) {
    const duration = Date.now() - start;
    console.error(`❌ PDF 生成失败 | 耗时: ${duration}ms | 错误:`, error.message);
    res.status(500).json({ error: 'PDF 生成失败', message: error.message });
  }
});



// ========================
// 通过 URL 生成 PDF
// ========================
app.post('/url-to-pdf', async (req, res) => {
  const { url, pdfOptions = {} } = req.body;
  const start = Date.now();

  console.log(`\n🌐 开始 URL 转 PDF | URL: ${url} | 时间: ${new Date().toISOString()}`);

  // 参数校验
  if (!url) {
    return res.status(400).json({ error: '缺少参数: url' });
  }

  // 检查 browser 状态
  if (!browser || !browser.isConnected()) {
    console.error('❌ 浏览器未连接，请求失败');
    return res.status(500).json({ error: '服务暂时不可用，请稍后重试' });
  }

  let page;
  try {
    page = await browser.newPage();
    page.on('console', msg => console.log('[PAGE] ' + msg.text()));
    page.on('error', err => console.error('[PAGE ERROR] ' + err));
    page.on('pageerror', err => console.error('[PAGE EXCEPTION] ' + err.message));

    // 设置用户代理（可选）
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');

    // 访问目标 URL
    const response = await page.goto(url, {
      waitUntil: 'networkidle0', // 等待网络空闲
      timeout: 30000 // 30秒超时
    });

    if (!response.ok()) {
      return res.status(400).json({ error: `页面加载失败: ${response.status} ${response.statusText}` });
    }

    // 合并默认 PDF 选项
    const options = {
      format: 'A4',
      printBackground: true,
      margin: {
        top: '20px',
        right: '20px',
        bottom: '20px',
        left: '20px'
      },
      ...pdfOptions
    };

    const pdfBuffer = await page.pdf(options);
    await page.close();

    const duration = Date.now() - start;
    console.log(`✅ URL 转 PDF 成功 | 耗时: ${duration}ms`);

    res.set({
      'Content-Type': 'application/pdf',
      'Content-Length': pdfBuffer.length,
      'Content-Disposition': 'attachment; filename=document.pdf'
    });
    res.send(pdfBuffer);

  } catch (error) {
    if (page) await page.close().catch(() => {});
    const duration = Date.now() - start;
    console.error(`❌ URL 转 PDF 失败 | 耗时: ${duration}ms | 错误:`, error.message);
    res.status(500).json({ 
      error: 'URL 转 PDF 失败', 
      message: error.message 
    });
  }
});

// ========================
// 启动服务
// ========================
async function startServer() {
  try {
    browser = await launchBrowser();
    printRoutes();
    printTemplates();

    // ✅ 添加这一行：让 Express 监听端口
    app.listen(3000, () => {
      console.log('✅ 服务已启动：http://localhost:3000');
    });

  } catch (err) {
    console.error('❌ 启动失败:', err);
    process.exit(1);
  }
}

startServer();

// ========================
// 优雅关闭
// ========================
process.on('SIGINT', async () => {
  console.log('\n🛑 正在关闭浏览器...');
  if (browser) await browser.close();
  process.exit(0);
});